#include "include/job.hpp"
#include "include/job_manager.hpp"
#include "include/kernel.hpp"
#include "include/logger.hpp"

using namespace qOS;

// Example Task function
int dataProcessingTask(uint64_t token, TlsfYoungAgeString& syncTaskData, void *userData) {
    static int counter = 0;
    counter++;
    
    logger::out(logger::info) << "Data processing task executed, counter: " << counter;
    
    // Simulate data processing work
    for (volatile int i = 0; i < 1000; i++);
    
    return 0;
}

int communicationTask(uint64_t token, TlsfYoungAgeString& syncTaskData, void *userData) {
    static int counter = 0;
    counter++;
    
    logger::out(logger::info) << "Communication task executed, counter: " << counter;
    
    // Simulate communication work
    for (volatile int i = 0; i < 500; i++);
    
    return 0;
}

int monitoringTask(uint64_t token, TlsfYoungAgeString& syncTaskData, void *userData) {
    static int counter = 0;
    counter++;
    
    logger::out(logger::info) << "Monitoring task executed, counter: " << counter;
    
    // Simulate monitoring work
    for (volatile int i = 0; i < 200; i++);
    
    return 0;
}

int controlTask(uint64_t token, TlsfYoungAgeString& syncTaskData, void *userData) {
    static int counter = 0;
    counter++;
    
    logger::out(logger::info) << "Control task executed, counter: " << counter;
    
    // Simulate control work
    for (volatile int i = 0; i < 800; i++);
    
    return 0;
}

// Idle task callback
void idleTaskCallback(event_t e, uint64_t securityToken) {
    if (e.firstCall()) {
        logger::out(logger::info) << "Idle task started";
    }
    
    // Security token verification
    if (securityToken != e.thisTask().GetSecurityToken()) {
        return;
    }
    
    // Idle task can perform some low-priority work
    static int idleCounter = 0;
    if (idleCounter++ % 1000 == 0) {
        logger::out(logger::debug) << "Idle task running...";
    }
}

int main() {
    // Create operating system instance
    core os;
    
    // Initialize operating system
    if (!os.init()) {
        logger::out(logger::error) << "Failed to initialize OS";
        return -1;
    }
    
    // Create Job manager
    JobManager jobManager(5); // Maximum 5 concurrent Jobs
    
    // Initialize Job manager
    if (!jobManager.initialize(os)) {
        logger::out(logger::error) << "Failed to initialize Job Manager";
        return -1;
    }
    
    // Create example Task array
    const size_t taskCount = 4;
    task taskArray[taskCount];
    
    // Configure Task functions
    // Note: RealTimeTask functions need to be adapted to the Job system here
    // Simplified implementation, using fixed Task configuration directly
    
    // Create Job configurations with timing constraints
    JobTimingAttr timing1(0, 10000, 5000, 2000, 500, 0);  // Release at 0, deadline 10ms, period 5ms, WCET 2ms
    JobTimingAttr timing2(2000, 8000, 3000, 1500, 300, 0); // Release at 2ms, deadline 8ms, period 3ms, WCET 1.5ms
    JobTimingAttr timing3(1000, 15000, 10000, 3000, 1000, 0); // Release at 1ms, deadline 15ms, period 10ms, WCET 3ms
    
    JobConfig job1Config("DataProcessingJob", JobExecutionMode::SEQUENTIAL, 5000, 3, true, timing1);
    JobConfig job2Config("CommunicationJob", JobExecutionMode::PARALLEL, 3000, 2, true, timing2);
    JobConfig job3Config("MonitoringJob", JobExecutionMode::PIPELINE, 10000, 1, false, timing3);
    
    // Create Job objects
    Job job1(job1Config);
    Job job2(job2Config);
    Job job3(job3Config);
    
    
    // Add Jobs to manager and submit with tasks
    if (!jobManager.addJobAndSubmit(job1, os, taskArray, taskCount)) {
        logger::out(logger::error) << "Failed to add and submit Job 1";
        return -1;
    }
    
    if (!jobManager.addJobAndSubmit(job2, os, taskArray, taskCount)) {
        logger::out(logger::error) << "Failed to add and submit Job 2";
        return -1;
    }
    
    if (!jobManager.addJobAndSubmit(job3, os, taskArray, taskCount)) {
        logger::out(logger::error) << "Failed to add and submit Job 3";
        return -1;
    }
    
    // Add dependency relationships (example)
    JobDependency dep1(0, 1); // Task 1 can only execute after Task 0 completes
    JobDependency dep2(1, 2); // Task 2 can only execute after Task 1 completes
    
    job1.addDependency(dep1);
    job1.addDependency(dep2);
    
    
    
    // Demonstrate timing constraint checking
    logger::out(logger::info) << "Job Timing Information:";
    
    JobTimingAttr timing1 = job1.getTimingAttributes();
    logger::out(logger::info) << "Job 1 - Periodic: " << job1.isPeriodic() 
                              << ", Period: " << timing1.period << "us";
    
    JobTimingAttr timing2 = job2.getTimingAttributes();
    logger::out(logger::info) << "Job 2 - Periodic: " << job2.isPeriodic() 
                              << ", Period: " << timing2.period << "us";
    
    JobTimingAttr timing3 = job3.getTimingAttributes();
    logger::out(logger::info) << "Job 3 - Periodic: " << job3.isPeriodic() 
                              << ", Period: " << timing3.period << "us";
    
    // Add idle task
    task idleTask;
    os.add(idleTask, idleTaskCallback, core::LOWEST_PRIORITY,
           clock::IMMEDIATE, task::PERIODIC, taskState::ENABLED_STATE);
    idleTask.setName("IdleTask");
    
    logger::out(logger::info) << "Job System initialized successfully";
    logger::out(logger::info) << "Job Manager Status:";
    jobManager.printStatus();
    
    logger::out(logger::info) << "Starting scheduler with Job System...";
    
    // Start scheduler
    os.run();
    
    return 0;
}

// Job统计信息输出操作符重载（简化实现）
qOS::logger& operator<<(qOS::logger& log, const qOS::JobStatistics& stats) {
    log << "Executions: " << stats.executionCount 
        << ", Success: " << stats.successCount 
        << ", Failures: " << stats.failureCount
        << ", Last Time: " << stats.lastExecutionTime << "us";
    return log;
}